/* @flow */

//  全局配置项
import config from '../config'
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'
import { warn, extend, nextTick, mergeOptions, defineReactive} from '../util/index'

/** 
 * 全局api: 
 * Vue.extend
 * Vue.nextTick
 * Vue.set
 * Vue.delete
 * Vue.directive
 * Vue.filter
 * Vue.component
 * Vue.use
 * Vue.mixin
 * Vue.compile
 * Vue.version
 *  该方法的作用是以静态属性和方法的形式将这些全局API添加到Vue的构造函数上
 * */ 
export function initGlobalAPI (Vue: GlobalAPI) {
  // 定义属性，用来获取config(即：core/config.js 文件导出的对象)(只读：只有get方法)
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  // 在Vue的构造函数上添加config属性，即Vue.config代理的是从 core/config.js 文件导出的对象
  Object.defineProperty(Vue, 'config', configDef)

  // 在Vue上添加了util属性(一个对象，其中的属性均来自于 core/util/index.js)
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive
  }
  // 定义全局属性
  Vue.set = set
  Vue.delete = del
  Vue.nextTick = nextTick
  
  // 通过Object.create(null)创建一个继承于null的对象，而null没有任何原型属性和方法，这样创建出的对像的原型属性和方法就全是空，方便自己添加原型属性和方法
  Vue.options = Object.create(null)
  /** 
   * 执行完Vue.options对象如下：
   * Vue.options.components = {}
   * Vue.options.directives = {}
   * Vue.options.filters = {}
   * */ 
  ASSET_TYPES.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  })

  /** 
   * 此时Vue.options对象如下：
   * Vue.options.components = {}
   * Vue.options.directives = {}
   * Vue.options.filters = {}
   * Vue.options._base= Vue
   * */ 
  Vue.options._base = Vue

  /**
   * extend 来自于 shared/util.js, 其作用是将builtInComponents 的属性混合到 Vue.options.components 中
   * builtInComponents来自于 core/components/index.js, 混合后得到：
   * Vue.options.components = {
   * 	 KeepAlive
   * }
   */
  extend(Vue.options.components, builtInComponents)

  /**
   * 代码执行到这里, Vue.options对象就变成了：
   * 
   * Vue.options = {
   * 	 components: {
   * 		 KeepAlive
   * 	 },
   *   directives: Object.create(null),
   *   filters: Object.create(null),
   *   _base: Vue
   * } 
   * 
  */
  // 初始化use方法，即Vue.use 用来安装插件
  initUse(Vue)
  // 在 Vue 上添加 mixin方法
  initMixin(Vue)
  // 在 Vue 上添加了 Vue.cid 静态属性，和 Vue.extend 静态方法
  initExtend(Vue)
  // 在Vue上挂载三个静态方法：Vue.component，Vue.directive，Vue.filter(全局注册组件，指令和过滤器)
  initAssetRegisters(Vue)
}
